package com.spzx.payment.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.core.utils.ip.IpUtils;
import com.spzx.common.core.web.controller.BaseController;
import com.spzx.common.core.web.domain.AjaxResult;
import com.spzx.common.rabbitmq.service.RabbitmqService;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.order.api.RemoteOrderService;
import com.spzx.order.domain.OrderInfo;
import com.spzx.payment.config.AlipayConfig;
import com.spzx.payment.domain.PaymentInfo;
import com.spzx.payment.service.IPaymentInfoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

//@RestController
@Controller
@RequestMapping("alipay")
@Slf4j
@Tag(name = "支付宝支付模块")
public class AlipayController extends BaseController {
    @Resource
    IPaymentInfoService paymentInfoService;
    @Resource
    RemoteOrderService remoteOrderService;
    @Resource
    RabbitmqService rabbitmqService;
    @Resource
    RedisTemplate redisTemplate;
    //用户如果支付完成 需要修改订单状态 库存销量

    //返回结果需要转为json： 如果是Controller注解，接口上必须添加@ResponseBody注解
    //alipay/submitAlipay/711240d196654515bb42eb873c088632


    @Operation(summary = "同步回调接口：支付宝完成页点击完成按钮") //只是为了让前端跳转到 成功或者失败的页面中
    @GetMapping("returnUrl")
    // 请求域是 request.getAttributes() 后端用来在一次请求中共享数据使用的
    // 请求参数是 request.getParameter() 前端用来在url地址后拼接参数提交到后端的
    public String returnUrl(@RequestParam Map<String,String> params){
        //直接使用Map相当于 model 代表请求域 ， 但是需要接收请求参数列表 必须使用@RequestParam注解
        //简单的判断用户支付成功还是失败
        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        //商户订单号: spzx的订单号
        String out_trade_no = params.get("out_trade_no");
        //支付宝交易号： 用户在支付宝支付时生成的交易编号
        String trade_no = params.get("trade_no");
        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        //计算得出通知验证结果： 验证签名
        //   获取支付宝传给我们的参数，使用支付宝的公钥对参数进行验签
        boolean verify_result = false;
        try {
            verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY,
                    AlipayConfig.CHARSET, AlipayConfig.SIGNTYPE);
            if(verify_result){//验证成功
                //////////////////////////////////////////////////////////////////////////////////////////
                //请在这里加上商户的业务逻辑程序代码
                //在判断用户支付是否成功：
                //1、如果成功：让浏览器跳转前端的支付成功页面  http://192.168.123.111/#/pages/money/paySuccess
                return "redirect:http://192.168.10.130/#/pages/money/paySuccess";
                //2、如果用户支付失败： 让浏览器跳转前端的支付取消页面  没有 前端可以写一个

            }else{
                //签名验证失败，证明支付宝回传的支付信息 被篡改了
                // 跳转到失败的非法请求页面
                //该页面可做页面美工编辑
                return "redirect:http://192.168.10.130/#/pages/money/payError";
            }

        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }


    }

    @ResponseBody
    @Operation(summary = "确认支付：跳转到支付宝支付页")
    @GetMapping("submitAlipay/{orderNo}")
    public AjaxResult submitAlipay(@PathVariable("orderNo") String orderNo) {
        // 商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = orderNo;
            /*
                远程调用 查询订单的详情
             */
        //TODO 查询订单的详情
        R<OrderInfo> orderInfoR = remoteOrderService.getPaymentInfo(orderNo);
        if(orderInfoR.getCode()!=200){
            throw new ServiceException(orderInfoR.getMsg());
        }
        OrderInfo orderInfo = orderInfoR.getData();
        // 订单名称，必填
        String subject = "尚品甄选";
        // 付款金额，必填
        String total_amount = orderInfo.getTotalAmount().toString();
        // 超时时间 可空
        String timeout_express = "3m";
        // 销售产品码 必填
        String product_code = "QUICK_WAP_WAY";
        /**********************/
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        // sdk需要引入依赖：alipay-sdk-java
        //调用RSA签名方式
        AlipayClient client = new DefaultAlipayClient(
                AlipayConfig.URL, //支付宝网关地址，测试环境应该使用沙箱地址：
                AlipayConfig.APPID, // spzx在支付宝创建的应用、并且绑定公钥私钥的app的ip，测试使用沙箱应用appId
                AlipayConfig.RSA_PRIVATE_KEY, // spzx生成的私钥
                AlipayConfig.FORMAT,
                AlipayConfig.CHARSET,
                AlipayConfig.ALIPAY_PUBLIC_KEY, //沙箱应用我们配置spzx公钥后 沙箱应用给我们的支付宝公钥
                AlipayConfig.SIGNTYPE); //后面封装的参数  支付宝会采用 我们配置的spzx的私钥对表单数据加签处理得到签名一起提交给支付宝
        AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

        // 封装请求支付信息
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(out_trade_no);
        model.setSubject(subject);
        model.setTotalAmount(total_amount);
        model.setTimeoutExpress(timeout_express);
        model.setProductCode(product_code);
        alipay_request.setBizModel(model);
        // 设置异步通知地址
        alipay_request.setNotifyUrl(AlipayConfig.notify_url);
        // 设置同步地址
        alipay_request.setReturnUrl(AlipayConfig.return_url);

        // form表单生产
        String form = "";
        try {
            // 调用SDK生成表单： 根据上面的参数 构建一个自动提交的表单页面字符串
            //   本质是一个 html页面，由form标签 和form内的表单项组成，最后编写了js代码 触发表单的自动提交
            // 如果浏览器解析form表单内容，会自动将表单数据提交给 表单的action地址
            form = client.pageExecute(alipay_request).getBody();
//            System.out.println(form);
            //记录交易日志

//                return AjaxResult.success("SUCCESS" , form);
            return success(form); // 虽然将form表单字符串设置给了 响应对象的message属性，但是前端就是解析message属性使用。
        } catch (AlipayApiException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }

    }
}
